<?php

class Adept_Template_Parser_Tpl_Rules 
{

    protected $singleQuoteLiteral;
    protected $doubleQuoteLiteral;
    protected $literal;
    protected $integerConst;
    protected $floatConst;
    protected $varMath;
    protected $varMathVar;
    protected $varBracket;
    protected $varGuts;
    protected $varBinding;
    protected $constValue;
    protected $generalValue;
    protected $objExt;
    protected $objRestrictedParam;
    protected $objSingleParam;
    protected $objParams;
    protected $objStart;
    protected $objCall;
    protected $objNextStart;
    protected $objNextCall;
    protected $obj;
    protected $generalValueOrObject;
    protected $modificatorParameter;
    protected $modificatorParameterMatch;
    protected $modificator;
    protected $modificatorMatch;
    protected $expression;
    protected $expressionMatch;
    protected $tagAttribute;
    protected $tagAttributeMatch;
    protected $tag;
    protected $tagMatch;
    protected $processingInstruction;
    
    static protected $instance = null;
    
    public function __construct()
    {
        $this->singleQuoteLiteral = '\'(?:[^\\\']*)\'';
        $this->doubleQuoteLiteral = '"(?:[^\"]*)"';
        
        $this->literal = '(?:' . $this->singleQuoteLiteral . '|' . $this->doubleQuoteLiteral . ')';
        
		$this->integerConst = '[\-\+]?\d+';
		$this->floatConst = '[\-\+]?\d+(?:\.\d+)?';        
        $this->varMath = '(?:[\+\*\/\%]|(?:-(?!>)))';		
        $this->varMathVar = '[\$\w\.\+\-\*\/\%\d\>\[\]\s]';        
		
		$this->varBracket = '\[\$?[\w\.]+\]';		
		$this->varGuts = '\w+(?:' . $this->varBracket . ')*(?:\.\$?\w+(?:' 
    	   . $this->varBracket . ')*)*';
            	   
    	$this->varBinding = '\$' . $this->varGuts;
            
        $this->constValue = '(?:' . $this->floatConst . '|' . $this->literal . ')';
        $this->generalValue = '(?:' . $this->varBinding . '|' . $this->floatConst . '|' 
    	   . $this->literal . ')';

        $this->objExt = '(?:->(?:\$?' . $this->varGuts . '))';
        
        $this->objRestrictedParam = '(?:(?:' . $this->generalValue . ')(?:'
    	   . $this->objExt . '(?:\(\s*(?:(?:' . $this->generalValue . ')'
    	   . '(?:\s*,\s*(?:' . $this->generalValue . '))*)?\s*\))?)*)';    	   
    	   
        $this->objSingleParam = '(?:\w+|' . $this->objRestrictedParam . '(?:\s*,\s*(?:(?:\w+|'
        	. $this->varBinding . $this->objRestrictedParam . ')))*)';
        $this->objParams  = '\(\s*(?:' . $this->objSingleParam . '(?:\s*,\s*' . $this->objSingleParam . ')*)?\s*\)';
        $this->objStart = '(?:' . $this->varBinding . '(?:' . $this->objExt . ')+)';
        

        $this->objCall = '(?:' . $this->objStart . '(?:' . $this->objParams . ')?(?:' . $this->varMath
        	. '(?:' . $this->floatConst . '|' . $this->varMathVar . ')*)?)';
        		
        $this->objNextStart = '(?:' . $this->objExt . ')';
        $this->objNextCall = '(?:' . $this->objNextStart . '(?:' . $this->objParams . ')?(?:' . $this->varMath
        	. '(?:' . $this->floatConst . '|' . $this->varMathVar . ')*)?)';
        
        $this->obj = '(?:' . $this->objCall . '(?:' . $this->objNextCall .')*)';
        
        $this->generalValueOrObject = '(?:' . $this->obj  . '|' . $this->varBinding . '|' . 
            $this->literal . '|' . $this->floatConst . ')';
    
        $this->modificatorParameter = '(?::' . $this->generalValueOrObject . ')';
        $this->modificatorParameterMatch = '(?::(' . $this->generalValueOrObject . '))';
        
        $this->modificator = '(?:\|\w+' . $this->modificatorParameter . '*)';    
        $this->modificatorMatch = '\|(\w+)(' . $this->modificatorParameter . '*)';
        
        $this->expression = $this->generalValueOrObject . '(?:' . $this->modificator . ')*';
        $this->expressionMatch = '(' . $this->generalValueOrObject .  ')((?:' . $this->modificator . ')*)';            
        $this->tagAttribute = '\s*(?:[\w\:\-]+)\s*=\s*(?:' . $this->expression . ')';        
        $this->tagAttributeMatch = '\s*([\w\:\-]+)\s*=\s*(' . $this->expression . ')';

        $this->tag = '[\/]?[\w\:\-]+\s*(?:' . $this->tagAttribute . ')*\s*[\/]?\s*';
        $this->tagMatch = '([\/]?)([\w\:\-]+)\s*((?:' . $this->tagAttribute . ')*)\s*([\/]?)\s*';
    
        
        $this->processingInstruction = '(?:\@(\w+)\s*(.*))';
    }
    
    static public function getInstance() 
    {
    	if (self::$instance == null) {
    		self::$instance = new self();
    	}
    	return self::$instance;
    }
    
    public function getLiteralRule()
    {
        return $this->literal;
    }
    
    public function getExpressionRule($match = false) 
    {
    	return ($match) ? $this->expressionMatch : $this->expression;
    }	
    
    public function getModificatorParameterRule($match = false) 
    {
    	return ($match) ? $this->modificatorParameterMatch : $this->modificatorParameter;
    }	    
    
    public function getModificatorRule($match = false) 
    {
    	return ($match) ? $this->modificatorMatch : $this->modificator;
    }	    
    
    public function getTagAttributeRule($match = false)
    {
        return ($match) ? $this->tagAttributeMatch : $this->tagAttribute;
    }
    
    public function getTagRule($match = false) 
    {
        return ($match) ? $this->tagMatch : $this->tag;
    }
    
    public function getConstValueRule() 
    {
    	return $this->constValue;
    }
    
    public function getProcessingInstructionRule()
    {
        return $this->processingInstruction;
    }
    
}
